#ifndef __LOCK_H__
#define __LOCK_H__

#include <semaphore.h>
#include <pthread.h>
#include <stdint.h>
#include <atomic>
#include <iostream>

#include "noncopyable.h"
// #include "fiber.h"


namespace johnsonli
{
	//信号量
	class SemaphoreLock : Noncopyable 
	{
	public:
        /**
        * @brief 构造函数
        * @param[in] count 信号量值的大小
        */
        SemaphoreLock(uint32_t count = 0);

        /**
         * @brief 析构函数
         */
        ~SemaphoreLock();

        /**
         * @brief 获取信号量
         */
        void wait();

        /**
         * @brief 释放信号量
         */
        void notify();
	private:
		sem_t m_semaphore;
	};

    //局部锁
    template<class T>
    class ScopedLockImpl
    {
    public:
        //构造函数，自动加锁
        ScopedLockImpl(T& mutex)
            :m_mutex(mutex)
        {
            lock();
            //std::cout << "加锁" << std::endl;
        }

        //析构函数，自动解锁
        ~ScopedLockImpl() {
            
            unlock();
            //std::cout << "解锁" << std::endl;
        }

        void lock() {
            if (!m_locked) {
                m_mutex.lock();
                m_locked = true;
            }
        }

        void unlock() {
            if (m_locked) {
                m_mutex.unlock();   
                m_locked = false;
            }
        }


    private:
        T& m_mutex;
        bool m_locked = false;
    };
    
    //互斥量
    class Mutex : Noncopyable 
    {
    public:
        /// 局部锁
        typedef ScopedLockImpl<Mutex> Lock;

        Mutex() 
        {
            pthread_mutex_init(&m_mutex, nullptr);
        }

        ~Mutex() 
        {
            pthread_mutex_destroy(&m_mutex);
        }

        void lock() 
        {
            pthread_mutex_lock(&m_mutex);
        }

        void unlock() 
        {
            pthread_mutex_unlock(&m_mutex);
        }
    private:
        /// mutex
        pthread_mutex_t m_mutex;
    };

    class NullMutex : Noncopyable
    {
    public:
        /// 局部锁
        typedef ScopedLockImpl<NullMutex> Lock;

        NullMutex() {}

        ~NullMutex() {}

        void lock() {}

        void unlock() {}
    };

    //局部读锁模板实现
    template<class T>
    class ReadScopedLockImpl 
    {
    public:
        /**
         * @brief 构造函数
         * @param[in] mutex 读写锁
         */
        ReadScopedLockImpl(T& mutex)
            :m_mutex(mutex) 
        {
            lock();
        }

        /**
         * @brief 析构函数,自动释放锁
         */
        ~ReadScopedLockImpl() 
        {
            unlock();
        }

        /**
         * @brief 上读锁
         */
        void lock() 
        {
            if (!m_locked) 
            {
                m_mutex.rdlock();
                m_locked = true;
            }
        }

        /**
         * @brief 释放锁
         */
        void unlock() 
        {
            if (m_locked) 
            {
                m_locked = false;
                m_mutex.unlock();     
            }
        }
    private:
        /// mutex
        T& m_mutex;
        /// 是否已上锁
        bool m_locked = false;
    };

    //局部写锁模板实现
    template<class T>
    class WriteScopedLockImpl 
    {
    public:
        /**
         * @brief 构造函数
         * @param[in] mutex 读写锁
         */
        WriteScopedLockImpl(T& mutex)
            :m_mutex(mutex) 
        {
            lock();
        }

        /**
         * @brief 析构函数
         */
        ~WriteScopedLockImpl() 
        {
            unlock();
        }

        /**
         * @brief 上写锁
         */
        void lock() 
        {
            if (!m_locked) 
            {
                m_mutex.wrlock();
                m_locked = true;
            }
        }

        /**
         * @brief 解锁
         */
        void unlock() 
        {
            if (m_locked) 
            {
                m_locked = false;
                m_mutex.unlock();    
            }
        }
    private:
        /// Mutex
        T& m_mutex;
        /// 是否已上锁
        bool m_locked = false;
    };

    //空读写锁 用于调试
    class NullRWMutex : Noncopyable
    {
    public:
        typedef ReadScopedLockImpl<NullRWMutex> ReadLock;
        typedef WriteScopedLockImpl<NullRWMutex> WriteLock;

    public:
        NullRWMutex() {}
        ~NullRWMutex() {}

        void rdlock() {}
        void wrlock() {}
        void unlock() {}
    };

    //读写锁
    class RWMutex : Noncopyable
    {
    public:
        /// 局部读锁
        typedef ReadScopedLockImpl<RWMutex> ReadLock;

        /// 局部写锁
        typedef WriteScopedLockImpl<RWMutex> WriteLock;

    public:
        RWMutex()
        {
            pthread_rwlock_init(&m_lock, nullptr);
        }

        ~RWMutex()
        {
            pthread_rwlock_destroy(&m_lock);
        }

        //读锁
        void rdlock()
        {
            pthread_rwlock_rdlock(&m_lock);
        }

        //写锁
        void wrlock() {
            pthread_rwlock_wrlock(&m_lock);
        }

        //解锁
        void unlock() {
            pthread_rwlock_unlock(&m_lock);
        }
    private:
        pthread_rwlock_t m_lock;
    };

    //自旋锁
    class SpinLock : Noncopyable
    {
    public:
        /// 局部锁
        typedef ScopedLockImpl<SpinLock> Lock;

        SpinLock()
        {
            pthread_spin_init(&m_mutex, 0);
        }

        ~SpinLock()
        {
            pthread_spin_destroy(&m_mutex);
        }

        void lock() 
        {
            pthread_spin_lock(&m_mutex);
        }

        void unlock()
        {
            pthread_spin_unlock(&m_mutex);
        }
    private:
        /// 自旋锁
        pthread_spinlock_t m_mutex;
    };

    //原子锁
    class CASLock : Noncopyable 
    {
    public:
        /// 局部锁
        typedef ScopedLockImpl<CASLock> Lock;

        CASLock() 
        {
            m_mutex.clear();
        }

        ~CASLock() {}

        void lock()
        {
            while (std::atomic_flag_test_and_set_explicit(&m_mutex, std::memory_order_acquire));
        }

        void unlock() 
        {
            std::atomic_flag_clear_explicit(&m_mutex, std::memory_order_release);
        }
    private:
        /// 原子状态
        volatile std::atomic_flag m_mutex;
    };

    // class Scheduler;
    // class FiberSemaphore : Noncopyable {
    // public:
    //     typedef SpinLock MutexType;

    //     FiberSemaphore(size_t initial_concurrency = 0);
    //     ~FiberSemaphore();

    //     bool tryWait();
    //     void wait();
    //     void notify();

    //     size_t getConcurrency() const { return m_concurrency;}
    //     void reset() { m_concurrency = 0;}
    // private:
    //     MutexType m_mutex;
    //     std::list<std::pair<Scheduler*, Fiber::ptr>> m_waiters;
    //     size_t m_concurrency;
    // };

}






#endif // !__LOCK__H

